#include "../include/TaskQueue.h"

TaskQueue::TaskQueue(size_t queSize)
: _queSize(queSize)
, _que()
, _mutex()
, _notEmpty(_mutex)
, _notFull(_mutex)
, _flag(true)
{

}

TaskQueue::~TaskQueue()
{

}

bool TaskQueue::empty() const
{
    return 0 == _que.size();
}

bool TaskQueue::full() const
{
    return _que.size() == _queSize;
}

void TaskQueue::push(ElemType &&task)
{
    //RAII的思想：利用栈对象的生命周期管理资源
    MutexLockGuard autoLock(_mutex);

    //虚假唤醒的问题
    while(full())
    {
        //如果为满，那么等待在该条件变量上的线程需要睡眠
        _notFull.wait();
    }

    //只有TaskQueue是不满，才可以push数据
    _que.push(std::move(task));

    //如果TaskQueue有数据，那么就需要唤醒对应的线程消费数据
    _notEmpty.notify();
}

ElemType TaskQueue::pop()
{
    MutexLockGuard autoLock(_mutex);

    while(empty() && _flag)
    {
        //如果为空，那么等待在该条件变量上的线程需要睡眠
        _notEmpty.wait();
    }

    if(_flag)
    {
        //只有TaskQueue是不空，才可以pop数据
        ElemType tmp = _que.front();//先获取该值
        _que.pop();//然后在进行删除

        //如果TaskQueue有空位置，那么就需要唤醒对应的线程生产数据
        _notFull.notify();

        return tmp;
    }
    else
    {
        return nullptr;
    }

}
//将所有等待在_notEmpty条件变量上的线程唤醒
void TaskQueue::wakeup()
{
    _flag = false;
    _notEmpty.notifyAll();
}
